﻿
using System;
using System.Collections.Generic;
using System.Linq;

using System.Xml;
using System.Xml.Linq;


namespace DDD.Infrastructure.Extend
{
    /// <summary>
    /// Xml 扩展操作类
    /// </summary>
    public static class LinqToXmlExtensions
    {
        /// <summary>
        /// 将XmlNode转换为XElement
        /// </summary>
        /// <returns> XElment对象 </returns>
        public static XElement ToXElement(this XmlNode node)
        {
            XDocument xdoc = new XDocument();
            using (XmlWriter xmlWriter = xdoc.CreateWriter())
            {
                node.WriteTo(xmlWriter);
            }
            return xdoc.Root;
        }


        /// <summary>
        /// 转成元素集合
        /// </summary>
        /// <param name="elements">元素</param>
        /// <param name="elementName">元素名</param>
        /// <returns></returns>
        public static IEnumerable<XElement> ToXElements(this IEnumerable<XElement> elements,string elementName)
        {
            if (elementName.IsNullOrEmpty())
            {
                return elements.Elements();
            }
            return elements.Elements(elementName);
        }


        /// <summary>
        /// 转成元素集合
        /// </summary>
        /// <param name="elements">要转换的元素集合</param>
        /// <returns></returns>
        public static IEnumerable<XElement> ToXElements(this IEnumerable<XElement> elements)
        {
            return elements.ToXElements(string.Empty);
        }


        /// <summary>
        /// 转成元素集合
        /// </summary>
        /// <param name="source">要转换的元素集合</param>
        /// <param name="predicate">查询的条件</param>
        /// <returns></returns>
        public static IEnumerable<XElement> ToXElements(this IEnumerable<XElement> source,
            Func<XElement, bool> predicate)
        {
            if (predicate == null)
            {
                return source.ToXElements();
            }
            return source.Where(predicate).ToXElements();
        }

        public static IEnumerable<TResult> ToXElements<TResult>(this IEnumerable<XElement> source,
    Func<XElement, bool> predicate, Func<XElement, TResult> selector)
        {
            if (predicate == null)
            {
                return source.Select(selector);
            }
            return source.Where(predicate).Elements().Select(selector);
        }


        /// <summary>按文档顺序返回此文档或元素的经过筛选的子代元素集合。集合中只包括具有匹配 <see cref="T:System.Xml.Linq.XName" /> 的元素。</summary>
        /// <returns>
        /// <see cref="T:System.Xml.Linq.XElement" /> 的 <see cref="T:System.Collections.Generic.IEnumerable`1" />，其中包含与指定 <see cref="T:System.Xml.Linq.XName" /> 匹配的 <see cref="T:System.Xml.Linq.XContainer" /> 的子代元素。</returns>
        /// <param name="name">要匹配的 <see cref="T:System.Xml.Linq.XName" />。</param>
        public static IEnumerable<XElement> ToDescendants(this IEnumerable<XElement> elements,string name)
        {
            if (name.IsNullOrEmpty())
            return elements.Descendants();
            return elements.Descendants(name);
        }

        /// <summary>按文档顺序返回此文档或元素的经过筛选的子代元素集合。集合中只包括具有匹配 <see cref="T:System.Xml.Linq.XName" /> 的元素。</summary>
        /// <returns>
        /// <see cref="T:System.Xml.Linq.XElement" /> 的 <see cref="T:System.Collections.Generic.IEnumerable`1" />，其中包含与指定 <see cref="T:System.Xml.Linq.XName" /> 匹配的 <see cref="T:System.Xml.Linq.XContainer" /> 的子代元素。</returns>
        public static IEnumerable<XElement> ToDescendants(this IEnumerable<XElement> elements)
        {
            return elements.ToDescendants(string.Empty);
        }

        /// <summary>
        /// 将XElement转换为XmlNode
        /// </summary>
        /// <returns> 转换后的XmlNode </returns>
        public static XmlNode ToXmlNode(this XElement element)
        {
            using (XmlReader xmlReader = element.CreateReader())
            {
                XmlDocument xml = new XmlDocument();
                xml.Load(xmlReader);
                return xml;
            }
        }


        /// <summary>
        /// 得到特性
        /// </summary>
        /// <param name="element">元素</param>
        /// <param name="name">元素名</param>
        /// <returns></returns>
        public static string GetAttribute(this XElement element,string name)
        {

            return element?.Attribute(name)?.Value;
        }


        /// <summary>
        /// 得到XML数据
        /// </summary>
        /// <param name="url">xmlURl</param>
        /// <param name="elementName">要读取节点的名字</param>
        /// <returns>返回所读到的XML数据</returns>
        public static IEnumerable<XElement> GetXmlData(this string url, string elementName="")
        {
            //加载该文件
            XDocument xdoc = XDocument.Load(url);

           
            //获取xml文件中根元素（根节点）
            XElement root = xdoc.Root;
            //获取根元素中所有的直接子元素
            IEnumerable<XElement> eles = elementName.IsNullOrEmpty()?root?.Elements(): root?.Elements(elementName);
            
            return eles;
        }



    }
}